
#ifndef  RECOVERY_SUBCODESTATUS_H
#define  RECOVERY_SUBCODESTATUS_H

#include "Status.h"
#include <iostream>

namespace recovery {

class SubcodeStatus : public Status {
    using Code = Status::Code;
public:

    enum class Subcode {
        kNone = 0,
        kInvalid = 1,
        kMaxSubcode,
    };

	operator bool() const {
		return this->isOK();
	}

    static SubcodeStatus OK(){
        return SubcodeStatus(Code::kOK, Subcode::kNone);
    }
    static SubcodeStatus Invalid(const std::string_view & msg=""){
        return SubcodeStatus(Code::kSubcode, Subcode::kInvalid, msg);
    }
    ~SubcodeStatus() override{}

    std::string what() const override;
    Status toStatus(const std::string_view & msg = "") const override;

	SubcodeStatus(const SubcodeStatus & right);
	SubcodeStatus & operator =(const SubcodeStatus & right);

	SubcodeStatus(SubcodeStatus && right);
	SubcodeStatus & operator =(SubcodeStatus && right);

	bool operator ==(const SubcodeStatus & right) const {
		return Status::operator==(right) && _subcode == right._subcode;
	}
	bool operator !=(const SubcodeStatus & right) const{
		return Status::operator != (right) || _subcode != right._subcode;
	}

protected:
    SubcodeStatus(Code code=Code::kSubcode, Subcode subcode=Subcode::kNone, const std::string_view & msg="");
    virtual const char * getSubcodeState(int subcode) const;

private:
    int _subcode;
};

inline SubcodeStatus::SubcodeStatus(Code code, Subcode subcode, const std::string_view & msg)
: Status(code, msg)
, _subcode(static_cast<int>(subcode))
{
}

inline SubcodeStatus::SubcodeStatus(const SubcodeStatus & right)
: Status(right) //TODO: bug
, _subcode(right._subcode)
{
}
inline SubcodeStatus &  SubcodeStatus::operator =(const SubcodeStatus & right){
	if(this != &right){
		Status::operator=(right);
		_subcode = right._subcode;
	}
	return *this;
}

inline SubcodeStatus::SubcodeStatus(SubcodeStatus && right)
: Status(std::move(right))
, _subcode(std::move(right._subcode))
{
}
inline SubcodeStatus & SubcodeStatus::operator =(SubcodeStatus && right){
	if(this != &right){
		Status::operator=(std::move(right));
		_subcode = std::move(right._subcode);
	}
	return *this;
}

}// end of namespace recovery

#endif   /* RECOVERY_SUBCODESTATUS_H */
